import React from 'react';
import classNames from 'classnames';
import Icon from '../Icon';
import {dateFormat} from '../utils/Utils';
import './Date.less';

const weeks = ['日', '一', '二', '三', '四', '五', '六'];

class DateComp extends React.Component {
    displayName = 'DateComp';

    renderWeek () {
        return weeks.map((item, index) => {
            return <span key={index}>{item}</span>;
        });
    }

    clearHms (date) {
        date.setHours(0);
        date.setMinutes(0);
        date.setSeconds(0);
        date.setMilliseconds(0);
    }

    isBetween (range, date) {
        if (!date) {
            return false;
        }
        const start = range[0];
        const end = range[1];
        if (!start) {
            return false;
        }
        if (range.length === 1 && start.getTime() === date.getTime()) {
            return true;
        }
        if (range.length === 2 && start.getTime() <= date.getTime() && end.getTime() >= date.getTime()) {
            return true;
        }
        return false;
    }

    renderDays () {
        const {value, disabledDate, disabledPrev, disabledNext, selected, onHoverDate, overDate} = this.props;
        const today = new Date();
        this.clearHms(today);
        const current = this.props.current || this.clearHms(new Date());
        const first = current ? new Date(current) : new Date();
        first.setDate(1);
        this.clearHms(first);
        const last = new Date(first);
        last.setMonth(last.getMonth() + 1);
        last.setDate(0);
        const index = first.getDay() % 6;
        const days = [];
        for (let i = 0; i < index; i++) {
            days.push(null);
        }
        
        first.setDate(0);
        for (let i = 0; i < last.getDate(); i++) {
            days.push(new Date(first.setDate(first.getDate() + 1)));
        }

        const v = value ? new Date(value) : null;
        let disabledPrevDate = null;
        let disabledNextDate = null;
        if (disabledPrev) {
            disabledPrevDate = new Date(disabledPrev);
            this.clearHms(disabledPrevDate);
        }
        if (disabledNext) {
            disabledNextDate = new Date(disabledNext);
            this.clearHms(disabledNextDate);
        }
        return days.map((day, index) => {
            const isToday = day ? today.toLocaleDateString() === day.toLocaleDateString() : false;
            const isActive = value && day ? v.toLocaleDateString() === day.toLocaleDateString() : false;
            let disabled = disabledDate && typeof disabledDate === 'function' ? disabledDate(day) : false;
            if (disabledPrevDate && day) {
                disabled = disabled || (day.getTime() - disabledPrevDate.getTime() < 0);
            }
            if (disabledNextDate && day) {
                disabled = disabled || (day.getTime() - disabledNextDate.getTime() > 0);
            }
            const inRange = selected && day ? this.isBetween(selected, day) : false;
            const hoverDate = selected && selected.length === 1 && overDate ? [overDate, selected[0]] : [];
            hoverDate.length === 2 && hoverDate.sort((a, b) => {
                return a.getTime() - b.getTime();
            });
            const inHover = hoverDate && day ? this.isBetween(hoverDate, day) : false;
            
            const firstRange = selected && selected[0] && day && selected[0].getTime() === day.getTime();
            const lastRange = selected && selected[1] && day && selected[1].getTime() === day.getTime();
            const className = classNames('cm-date-picker-date', {
                'cm-date-picker-empty': !day,
                'cm-date-picker-today': isToday,
                'cm-date-picker-active': isActive,
                'cm-date-picker-inrange': !disabled && inRange,
                'cm-date-picker-inhover': !disabled && inHover,
                'cm-date-picker-first-range': firstRange,
                'cm-date-picker-last-range': lastRange,
                'cm-date-picker-disabled': disabled
            });
            return <div key={index} className={className} onClick={disabled ? undefined : this.onSelectDate.bind(this, day)} onMouseOver={onHoverDate && onHoverDate.bind(this, day)}>
                <em>{day ? day.getDate() : ''}</em>
            </div>;
        });
    }

    renderYears () {
        const {value, onSelectYear, disabledDate, disabledPrev, disabledNext} = this.props;
        const current = this.props.current || new Date();
        const first = current ? new Date(current) : new Date();
        const years = [];
        first.setFullYear(first.getFullYear() - 1);
        for (let i = 0; i < 9; i++) {
            years.push(new Date(first.setFullYear(first.getFullYear() + 1)));
        }
        const v = value ? new Date(value) : null;
        let disabledPrevDate = null;
        let disabledNextDate = null;
        if (disabledPrev) {
            disabledPrevDate = new Date(disabledPrev);
            this.clearHms(disabledPrevDate);
        }
        if (disabledNext) {
            disabledNextDate = new Date(disabledNext);
            this.clearHms(disabledNextDate);
        }
        return years.map((year, index) => {
            const isActive = v ? v.getFullYear() === year.getFullYear() : false;
            let disabled = disabledDate && typeof disabledDate === 'function' ? disabledDate(day) : false;
            if (disabledPrevDate && year) {
                disabled = disabled || (parseInt(dateFormat('yyyy', year), 10) - parseInt(dateFormat('yyyy', disabledPrevDate), 10) < 0);
            }
            if (disabledNextDate && year) {
                disabled = disabled || (parseInt(dateFormat('yyyy', year), 10) - parseInt(dateFormat('yyyy', disabledNextDate), 10) > 0);
            }
            const className = classNames('cm-date-picker-year', {
                'cm-date-picker-active': isActive,
                'cm-date-picker-disabled': disabled
            });
            return <div key={index} className={className} onClick={disabled ? undefined : onSelectYear.bind(this, year)}><em>{year.getFullYear()}</em></div>;
        });
    }

    renderMonths () {
        const {value, onSelectMonth, disabledDate, disabledPrev, disabledNext} = this.props;
        const current = this.props.current || new Date();
        const first = current ? new Date(current) : new Date();
        const ms = [];
        for (let i = 0; i < 12; i++) {
            ms.push(new Date(first.setMonth(i)));
        }
        const v = value ? new Date(value) : null;
        let disabledPrevDate = null;
        let disabledNextDate = null;
        if (disabledPrev) {
            disabledPrevDate = new Date(disabledPrev);
            this.clearHms(disabledPrevDate);
        }
        if (disabledNext) {
            disabledNextDate = new Date(disabledNext);
            this.clearHms(disabledNextDate);
        }
        return ms.map((month, index) => {
            const isActive = v ? `${v.getFullYear()}-${v.getMonth()}` === `${month.getFullYear()}-${month.getMonth()}` : false;
            let disabled = disabledDate && typeof disabledDate === 'function' ? disabledDate(day) : false;
            if (disabledPrevDate && month) {
                disabled = disabled || (parseInt(dateFormat('yyyyMM', month)) - parseInt(dateFormat('yyyyMM', disabledPrevDate)) < 0);
            }
            if (disabledNextDate && month) {
                disabled = disabled || (parseInt(dateFormat('yyyyMM', month)) - parseInt(dateFormat('yyyyMM', disabledNextDate)) > 0);
            }
            const className = classNames('cm-date-picker-month', {
                'cm-date-picker-active': isActive,
                'cm-date-picker-disabled': disabled
            });
            return <div key={index} className={className} onClick={disabled ? undefined : onSelectMonth.bind(this, month)}><em>{month.getMonth() + 1}月</em></div>;
        });
    }

    onSelectDate = (date) => {
        if (this.props.onChange) {
            this.props.onChange(date);
        }
    }

    onPrevYear = () => {
        let {current, onPrevYear, view} = this.props;
        if (!current) {
            current = new Date();
            this.clearHms(current);
        }
        let step = 1;
        if (view === 'year') {
            step = 9;
        }
        current.setFullYear(current.getFullYear() - step);
        onPrevYear && onPrevYear(current);
    }

    onNextYear = () => {
        let {current, onNextYear, view} = this.props;
        if (!current) {
            current = new Date();
            this.clearHms(current);
        }
        let step = 1;
        if (view === 'year') {
            step = 9;
        }
        current.setFullYear(current.getFullYear() + step);
        onNextYear && onNextYear(current);
    }

    onPrevMonth = () => {
        let {current, onPrevMonth} = this.props;
        if (!current) {
            current = new Date();
            this.clearHms(current);
        }
        current.setMonth(current.getMonth() - 1);
        onPrevMonth && onPrevMonth(current);
    }

    onNextMonth = () => {
        let {current, onNextMonth} = this.props;
        if (!current) {
            current = new Date();
            this.clearHms(current);
        }
        current.setMonth(current.getMonth() + 1);
        onNextMonth && onNextMonth(current);
    }

    render () {
        const {className, style, current, view, gotoYearView, gotoMonthView} = this.props;
        let c = current;
        if (!c) {
            c = new Date();
        }
        const clazzName = classNames('cm-date-picker', {
            [`cm-date-picker-view-${view}`]: view
        }, className);
        return <div className={clazzName} style={style}>
            <div className='cm-date-picker-header'>
                <Icon name='ios-arrow-back' className='cm-date-picker-prev-year cm-date-picker-header-btn' onClick={this.onPrevYear}><Icon name='ios-arrow-back'/></Icon>
                {
                    view === 'year' || view === 'month'
                        ? null
                        : <Icon name='ios-arrow-back' className='cm-date-picker-prev-month cm-date-picker-header-btn' onClick={this.onPrevMonth}/>
                }
                <span className='cm-date-picker-header-year' onClick={gotoYearView}>{c.getFullYear()}年</span>
                {
                    view === 'year' || view === 'month'
                        ? null
                        : <span className='cm-date-picker-header-month' onClick={gotoMonthView}>{c.getMonth() + 1}月</span>
                }
                <Icon name='ios-arrow-forward' className='cm-date-picker-next-year cm-date-picker-header-btn' onClick={this.onNextYear}><Icon name='ios-arrow-forward'/></Icon>
                {
                    view === 'year' || view === 'month'
                        ? null
                        : <Icon name='ios-arrow-forward' className='cm-date-picker-next-month cm-date-picker-header-btn' onClick={this.onNextMonth}/>
                }
            </div>
            <div className='cm-date-picker-body'>
                {
                    view === 'date'
                        ? <div className='cm-date-picker-week-line'>
                            {this.renderWeek()}
                        </div>
                        : null
                }
                <div className='cm-date-picker-days'>
                    {
                        view === 'date'
                            ? this.renderDays()
                            : null
                    }
                    {
                        view === 'year'
                            ? this.renderYears()
                            : null
                    }
                    {
                        view === 'month'
                            ? this.renderMonths()
                            : null
                    }
                </div>
            </div>
        </div>;
    }
}

export default DateComp;
